# Logistic Regression
# 梯度下降法，Sklearn库，混淆矩阵，ROC曲线AUC值

# import lib
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")

# def loaddata
def loaddata(filename):
    file = open(filename)
    x=[]
    y=[]
    for line in file.readlines():
        line = line.strip().split()
        x.append([1,float(line[0]),float(line[1])])
        y.append(float(line[-1]))
    xmat = np.mat(x)
    ymat = np.mat(y).T
    file.close()
    return xmat, ymat

# def sigmoid
def sigmoid(inX):
	return 1.0 / (1 + np.exp(-inX))

# 梯度下降法求最佳回归系数w
def classify(xmat,ymat,alpha=0.001,maxIter=90001):
    # 权值W初始化
    W = np.mat(np.random.randn(3,1))
    # 定一个记录权值结果的列表
    w_save = []
    # 更新权值W
    for i in range(maxIter):
        H = sigmoid(xmat*W)
        dw = xmat.T*(H-ymat) # dw:(3,1)
        W -= alpha * dw
        if i % 100 == 0 and i >= 70000:
            w_save.append([W.copy(),i])
    return W


xmat, ymat= loaddata('E:\Microsoft VS Code\VSCode\machine_learning\LR\dataSet.txt')
# predict
xmat_test, ymat_test= loaddata('E:\Microsoft VS Code\VSCode\machine_learning\LR\dataSet.txt')
# 可得到决策边界直线方程 x2 = -w0/w2 - (w1/w2)*x1
def datingClassTest(xmat_test):
    W = classify(xmat,ymat)
    w0 = W[0,0]
    w1 = W[1,0]
    w2 = W[2,0]
    #分类错误计数
    errorCount = 0.0
    predicted_labels1 = []
    for i in range(20):
        pre_xmat = -w0/w2 - (w1/w2)*xmat_test[i,1]
        if xmat_test[i,2] < pre_xmat:
            classifierResult = 0
        elif xmat_test[i,2] >= pre_xmat:
            classifierResult = 1
        print("分类结果: ",classifierResult,"真实类别: ",ymat_test[i])
        predicted_labels1.append(classifierResult)
        if classifierResult != ymat_test[i]:
            errorCount += 1.0
    print("准确率为:%f%%" %((len(ymat_test)-errorCount)/float(len(ymat_test))*100))
    return predicted_labels1

p = datingClassTest(xmat_test)

# 使用sklearn库
print("使用sklearn库进行分类的准确率为：")
# 逻辑回归分类器
from sklearn import metrics
from sklearn.linear_model import LogisticRegression
lgr = LogisticRegression(solver='sag',max_iter = 5000).fit(xmat, ymat)
predicted_labels=lgr.predict(xmat_test)
print('准确率为：', metrics.accuracy_score(ymat_test, predicted_labels))

#############画图部分
# 混淆矩阵
# from sklearn import metrics
# import seaborn as sns
# sns.set()
# f,ax=plt.subplots()
# C2= metrics.confusion_matrix(ymat_test[:20], predicted_labels[:20], labels=[0, 1])
# # C2= metrics.confusion_matrix(ymat_test[80:100],np.mat(p).T, labels=[0, 1])
# print('混淆矩阵为\n',C2) #打印出来看看
# sns.heatmap(C2,annot=True,ax=ax) #画热力图

# ax.set_title('confusion matrix-sklearn') #标题
# ax.set_xlabel('ypredict') #x轴
# ax.set_ylabel('ytrue') #y轴
# plt.show()

# Validation ROC
#fpr, tpr, threshold = metrics.roc_curve(ymat_test, predicted_labels)  # 自定义
fpr, tpr, threshold = metrics.roc_curve(p, predicted_labels)          # 引Sklearn库
roc_auc = metrics.auc(fpr, tpr)
plt.figure(figsize=(6,6))
plt.title('Validation ROC(Sklearn)')
plt.plot(fpr, tpr, 'b', label = 'Val AUC = %0.3f' % roc_auc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()